﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using WhatsPlayingClient.Audio;
using System.Collections.ObjectModel;
using Un4seen.Bass;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading.Tasks;
using Un4seen.Bass.AddOn.Enc;
using System.Net;

namespace WhatsPlayingClient
{
	/// <summary>
	/// Interaction logic for MainWindow.xaml
	/// </summary>
	public partial class MainWindow : Window
	{
		AudioFileReader reader = new AudioFileReader();
		ObservableCollection<AudioFile> files = new ObservableCollection<AudioFile>();

		public MainWindow()
		{
			InitializeComponent();

			Properties.Settings.Default.SettingsSaving += new System.Configuration.SettingsSavingEventHandler(Default_SettingsSaving);
			Closing += new System.ComponentModel.CancelEventHandler(MainWindow_Closing);

			textBoxDirectory.Text = Properties.Settings.Default.MusicDirectory;

			listBoxResults.ItemsSource = files;
		}

		void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			Properties.Settings.Default.Save();
		}

		void Default_SettingsSaving(object sender, System.ComponentModel.CancelEventArgs e)
		{
			Properties.Settings.Default.MusicDirectory = textBoxDirectory.Text;
		}

		private void buttonSelectDir_Click(object sender, RoutedEventArgs e)
		{
			var directory = textBoxDirectory.Text;
			var scheduler = TaskScheduler.FromCurrentSynchronizationContext();
			Task.Factory.StartNew(() =>
			{
				foreach (string fileName in Directory.EnumerateFiles(directory, "*.mp3", SearchOption.AllDirectories))
				{
					try
					{
						var file = reader.ReadFile(fileName);
						using (var debugFile = File.CreateText(fileName + ".bands"))
						{
							foreach (Spectrum spc in file.Spectrums)
							{
								debugFile.WriteLine("Count\t{0}", string.Join("\t", spc.Params.FreqBands.AsEnumerable()));
								foreach (var point in spc.SpectrumData)
									debugFile.WriteLine("{0}\t{1}", point.SpectrumCount, string.Join("\t", point.Spectrum));

								debugFile.WriteLine("---------------------------------------------------------------------");
								debugFile.WriteLine("---------------------------------------------------------------------");
								debugFile.WriteLine("---------------------------------------------------------------------");
							}
						}

						new Task(() => files.Add(file)).Start(scheduler);
					}
					catch (Exception ex)
					{
					}
				}

			});
		}

		private double dist(float[] p1, float[] p2)
		{
			double sum = 0;
			int len = Math.Min(p1.Length, p2.Length);
			for (int i = 0; i < len; i++)
				sum += (p1[i] - p2[i]) * (p1[i]-p2[i]);
			return Math.Sqrt(sum);
		}

		private double[] dists(float[] p1, float[] p2)
		{
			int len = Math.Min(p1.Length, p2.Length);
			double[] res = new double[len];
			for (int i = 0; i < len; i++)
				res[i] = (p1[i] - p2[i]) * (p1[i] - p2[i]);
			return res;
		}

		private bool IsFileSame(string s1, string s2)
		{
			return System.IO.Path.GetFileName(s1).ToLower().StartsWith(System.IO.Path.GetFileName(s2).ToLower().Substring(0, 3));
		}

		private Random random = new Random();

		private float[] GetRandomPoint(List<Tuple<string, Spectrum[]>> spectrums, int spec_id)
		{
			var file_idx = random.Next(spectrums.Count);
			var spec = spectrums[file_idx].Item2[spec_id];
			var point_idx = random.Next(spec.SpectrumData.Count);
			return spec.SpectrumData[point_idx].Spectrum;
		}

		private void CountAllStats()
		{
			var spectrums = new List<Tuple<string, Spectrum[]>>();
			foreach (var file in files)
				spectrums.Add(Tuple.Create(file.TagLibFile.Name, file.Spectrums));

			var samepairs = new List<Tuple<int, int>>();
			for (var i = 0; i < spectrums.Count; i++)
				for (var j = 0; j < i; j++)
					if (IsFileSame(spectrums[i].Item1, spectrums[j].Item1))
						samepairs.Add(Tuple.Create(i, j));

			var nspectrums = spectrums[0].Item2.Length;
			int npoints = spectrums.Sum((t) => t.Item2[0].SpectrumData.Count);
			for (var i = 0; i < nspectrums; i++)
			{
				int avgdistnsamples = npoints * 2;
				
				double distsum = 0;
				for (var j = 0; j < avgdistnsamples; j++)
					distsum += dist(GetRandomPoint(spectrums, i), GetRandomPoint(spectrums, i));
				distsum /= avgdistnsamples;

				double[] bandDistSums = new double[100];
				int[] bandDistCounts = new int[100];
				double distsamesum = 0;
				for (var j = 0; j < avgdistnsamples; j++)
				{
					var pair = samepairs[random.Next(samepairs.Count)];
					var spdata1 = spectrums[pair.Item1].Item2[i].SpectrumData;
					var spdata2 = spectrums[pair.Item2].Item2[i].SpectrumData;
					var point_idx = random.Next(Math.Min(spdata1.Count, spdata2.Count));
					distsamesum += dist(spdata1[point_idx].Spectrum, spdata2[point_idx].Spectrum);
					var d = dists(spdata1[point_idx].Spectrum, spdata2[point_idx].Spectrum);
					for (int k = 0; k < d.Length; ++k)
					{
						bandDistSums[k] += d[k];
						bandDistCounts[k]++;
					}
				}
				distsamesum /= avgdistnsamples;

				for (int k = 0; k < bandDistCounts.Length && bandDistCounts[k] > 0; ++k)
					bandDistSums[k] /= bandDistCounts[k];

				Trace.WriteLine(String.Format("Spectrum {0}: AvgDist - {1}; AvgSame - {2}; BandDists: {3}", i, 
					distsum, distsamesum, string.Join(", ", bandDistSums)));

			}
		}

		private List<float[]> char_points = new List<float[]> { 
 new float[] { (float)-17.93579, (float)-22.69912, (float)-23.5459, (float)-23.96589, (float)-25.8882, (float)-28.37512, (float)-33.3423, (float)0 }, 
 new float[] { (float)-12.71635, (float)-16.58555, (float)-18.01702, (float)-18.95025, (float)-19.61495, (float)-20.5523, (float)-21.48549, (float)-24.05093 }, 
 new float[] { (float)-66.12925, (float)-67.47884, (float)-68.56049, (float)-68.72713, (float)-68.57227, (float)-69.40077, (float)-70.3213, (float)-23.47856 }, 
 new float[] { (float)-16.70321, (float)-23.80627, (float)-26.49413, (float)-26.69493, (float)-28.44147, (float)-28.67309, (float)-31.91018, (float)0 }, 
 new float[] { (float)-15.77787, (float)-19.92393, (float)-21.20201, (float)-21.96964, (float)-22.47442, (float)-23.66495, (float)-24.92765, (float)-27.38157 }, 
 new float[] { (float)-12.58037, (float)-18.94477, (float)-22.17878, (float)-23.65272, (float)-24.59348, (float)-24.24656, (float)-23.48293, (float)-25.59566 }, 
 new float[] { (float)-17.69399, (float)-23.53629, (float)-25.66327, (float)-26.74664, (float)-27.57666, (float)-28.69634, (float)-30.1557, (float)-32.84807 }, 
 new float[] { (float)-27.36688, (float)-19.13436, (float)-20.06166, (float)-20.59685, (float)-19.72976, (float)-22.74054, (float)-29.31151, (float)-42.57519 }, 
 new float[] { (float)-18.91132, (float)-19.91217, (float)-21.90862, (float)-23.53283, (float)-23.25443, (float)-24.10295, (float)-26.2318, (float)-29.45209 }, 
 new float[] { (float)-24.18351, (float)-25.12148, (float)-27.65833, (float)-29.37384, (float)-28.32178, (float)-28.25636, (float)-28.03739, (float)-30.26719 }, 
 new float[] { (float)-16.47403, (float)-24.6909, (float)-25.57229, (float)-26.38354, (float)-27.18676, (float)-27.05016, (float)-26.02635, (float)-29.00191 }, 
 new float[] { (float)-28.43611, (float)-30.31276, (float)-32.96961, (float)-34.48264, (float)-33.65577, (float)-34.13509, (float)-33.39645, (float)-35.0368 }, 
 new float[] { (float)-27.72606, (float)-21.93128, (float)-23.27412, (float)-27.21566, (float)-28.57716, (float)-35.0587, (float)-42.23199, (float)-49.557 }, 
 new float[] { (float)-19.91508, (float)-26.59732, (float)-29.17239, (float)-30.91319, (float)-32.24239, (float)-33.26536, (float)-34.9016, (float)-38.16396 }, 
 new float[] { (float)-25.36038, (float)-34.59547, (float)-38.01418, (float)-39.38404, (float)-39.67353, (float)-40.72898, (float)-41.61726, (float)-45.54193 }, 
 new float[] { (float)-30.09283, (float)-29.36804, (float)-29.19579, (float)-29.61819, (float)-32.99587, (float)-34.95622, (float)-38.36424, (float)-44.71584 }, 
 new float[] { (float)-15.00836, (float)-18.42169, (float)-20.49874, (float)-21.85047, (float)-21.67233, (float)-21.09431, (float)-21.30186, (float)-24.15036 }, 
 new float[] { (float)-24.77786, (float)-25.5705, (float)-25.77673, (float)-26.72041, (float)-26.93654, (float)-29.17735, (float)-34.92824, (float)0 }, 
 new float[] { (float)-13.90642, (float)-18.85238, (float)-21.08806, (float)-21.72846, (float)-23.4, (float)-25.00492, (float)-26.87333, (float)-29.85098 }, 
 new float[] { (float)-21.64174, (float)-29.16065, (float)-29.92171, (float)-30.7701, (float)-31.04041, (float)-33.13732, (float)-37.76889, (float)0 }, 
 new float[] { (float)-28.33231, (float)-21.26174, (float)-22.67721, (float)-24.31827, (float)-24.96112, (float)-30.67276, (float)-36.99239, (float)-47.10066 }, 
 new float[] { (float)-15.93127, (float)-22.01116, (float)-24.59602, (float)-25.87849, (float)-26.66862, (float)-26.76905, (float)-29.51919, (float)0 }, 
 new float[] { (float)-17.93138, (float)-21.1665, (float)-22.53681, (float)-23.22189, (float)-26.72294, (float)-28.79554, (float)-30.56319, (float)-33.98074 }, 
 new float[] { (float)-29.01696, (float)-28.82302, (float)-29.83798, (float)-31.05974, (float)-30.53917, (float)-32.07676, (float)-37.31591, (float)0 }, 
 new float[] { (float)-17.99726, (float)-28.0682, (float)-28.06405, (float)-29.92647, (float)-29.08583, (float)-30.56282, (float)-30.33379, (float)-34.43054 }, 
 new float[] { (float)-17.4432, (float)-21.88834, (float)-22.23301, (float)-23.01051, (float)-23.87404, (float)-26.27458, (float)-30.22429, (float)0 }, 
 new float[] { (float)-21.73443, (float)-23.35781, (float)-22.5832, (float)-22.95653, (float)-23.79439, (float)-26.93684, (float)-32.64375, (float)0 }, 
 new float[] { (float)-15.53013, (float)-20.37827, (float)-23.33005, (float)-24.46889, (float)-25.58336, (float)-26.49326, (float)-27.62495, (float)-30.10355 }, 
 new float[] { (float)-24.69742, (float)-24.43543, (float)-24.70396, (float)-25.70528, (float)-25.94038, (float)-27.49372, (float)-30.81517, (float)-35.65286 }, 
 new float[] { (float)-16.18672, (float)-17.29286, (float)-18.77117, (float)-20.1935, (float)-22.93911, (float)-24.43804, (float)-25.73207, (float)-28.17888 }, 
 new float[] { (float)-44.30318, (float)-48.41467, (float)-50.73423, (float)-51.73523, (float)-52.61779, (float)-53.69152, (float)-55.80883, (float)-57.79274 }, 
 new float[] { (float)-31.30703, (float)-28.09744, (float)-24.61996, (float)-23.27506, (float)-25.24499, (float)-27.04269, (float)-29.33067, (float)-32.67593 }, 
 new float[] { (float)-14.78254, (float)-17.85291, (float)-19.44527, (float)-20.32529, (float)-21.45125, (float)-22.74212, (float)-25.02283, (float)-32.44581 }, 
 new float[] { (float)-34.02834, (float)-32.43904, (float)-32.26725, (float)-31.7424, (float)-34.73314, (float)-36.45592, (float)-42.35388, (float)0 }, 
 new float[] { (float)-12.9438, (float)-17.07671, (float)-19.64187, (float)-20.83516, (float)-21.09347, (float)-21.76204, (float)-23.83061, (float)-27.94514 }, 
 new float[] { (float)-18.40228, (float)-22.44002, (float)-24.50972, (float)-25.68077, (float)-27.89497, (float)-29.85524, (float)-33.19304, (float)-38.75353 }, 
 new float[] { (float)-28.02345, (float)-18.92441, (float)-18.48116, (float)-20.81484, (float)-22.47151, (float)-30.0801, (float)-37.85831, (float)-50.05956 }, 
 new float[] { (float)-32.34836, (float)-29.1184, (float)-26.76995, (float)-25.86753, (float)-27.29329, (float)-30.25294, (float)-35.6455, (float)0 }, 
 new float[] { (float)-17.22088, (float)-18.94611, (float)-19.43985, (float)-20.26735, (float)-19.79095, (float)-21.34999, (float)-24.26908, (float)-27.86423 }, 
 new float[] { (float)-15.61221, (float)-21.79271, (float)-26.34761, (float)-26.65608, (float)-24.60711, (float)-22.8221, (float)-25.25739, (float)-36.23145 }, 
 new float[] { (float)-14.67268, (float)-19.48524, (float)-19.64088, (float)-19.79719, (float)-21.10734, (float)-22.69309, (float)-23.61111, (float)-25.94219 }, 
 new float[] { (float)-11.12952, (float)-17.39057, (float)-20.10505, (float)-21.37568, (float)-22.55573, (float)-22.26053, (float)-21.8555, (float)-24.2702 }, 
 new float[] { (float)-14.44494, (float)-16.77225, (float)-18.3122, (float)-18.22586, (float)-18.36012, (float)-20.03237, (float)-22.60784, (float)-27.54591 }, 
 new float[] { (float)-28.75328, (float)-22.77159, (float)-23.36327, (float)-24.24984, (float)-23.36363, (float)-26.99617, (float)-32.1259, (float)-49.94418 }, 
 new float[] { (float)-27.70806, (float)-18.93178, (float)-18.89031, (float)-20.44425, (float)-20.58918, (float)-25.21564, (float)-31.91097, (float)-50.3841 }, 
 new float[] { (float)-30.15484, (float)-40.60598, (float)-43.48574, (float)-44.49537, (float)-44.39032, (float)-45.39833, (float)-49.11631, (float)0 }, 
 new float[] { (float)-16.07322, (float)-23.19627, (float)-22.91282, (float)-21.8533, (float)-24.32193, (float)-25.4083, (float)-25.96332, (float)-29.44768 }, 
 new float[] { (float)-26.29478, (float)-21.96758, (float)-22.15802, (float)-23.5622, (float)-26.21349, (float)-28.38083, (float)-29.9378, (float)-32.7696 }, 
 new float[] { (float)-15.04179, (float)-19.78692, (float)-23.48248, (float)-24.60009, (float)-22.84848, (float)-21.43201, (float)-23.64388, (float)-31.41525 }, 
 new float[] { (float)-16.24484, (float)-22.52668, (float)-24.24119, (float)-25.18448, (float)-25.53648, (float)-24.7527, (float)-23.74528, (float)-25.70122 }, 
 new float[] { (float)-20.02527, (float)-23.14293, (float)-25.13797, (float)-26.39116, (float)-25.96672, (float)-27.44501, (float)-34.45658, (float)0 }, 
 new float[] { (float)-20.50211, (float)-21.51887, (float)-22.55675, (float)-23.89958, (float)-27.11873, (float)-29.38594, (float)-33.78825, (float)0 }, 
 new float[] { (float)-15.49516, (float)-18.37203, (float)-16.52874, (float)-15.99284, (float)-20.37545, (float)-21.82156, (float)-23.86078, (float)-29.36434 }, 
 new float[] { (float)-17.91072, (float)-19.27424, (float)-19.97783, (float)-21.36385, (float)-24.59381, (float)-26.24827, (float)-27.76133, (float)-31.61715 }, 
 new float[] { (float)-27.02902, (float)-19.04745, (float)-20.6676, (float)-22.03671, (float)-22.60194, (float)-27.18034, (float)-33.29056, (float)-43.32585 }, 
 new float[] { (float)-32.83233, (float)-31.91191, (float)-29.79343, (float)-28.23061, (float)-28.00145, (float)-29.10346, (float)-32.32458, (float)-36.63889 }, 
 new float[] { (float)-28.05406, (float)-26.21189, (float)-25.98067, (float)-26.57778, (float)-28.09545, (float)-29.85179, (float)-33.35664, (float)-40.39685 }, 
 new float[] { (float)-19.04408, (float)-22.15963, (float)-23.9498, (float)-25.29669, (float)-25.45117, (float)-25.6969, (float)-29.91942, (float)0 }, 
 new float[] { (float)-19.99246, (float)-21.16801, (float)-20.14995, (float)-20.84223, (float)-21.66479, (float)-23.78737, (float)-26.03563, (float)-30.7288 }, 
 new float[] { (float)-23.40371, (float)-23.17264, (float)-22.05089, (float)-22.84613, (float)-22.8592, (float)-24.59232, (float)-27.03995, (float)-31.57829 }, 
 new float[] { (float)-16.25598, (float)-20.52125, (float)-22.28635, (float)-23.47965, (float)-23.58595, (float)-22.85369, (float)-22.26654, (float)-24.5652 }, 
 new float[] { (float)-20.70097, (float)-22.32812, (float)-23.46025, (float)-24.64006, (float)-25.01827, (float)-26.23803, (float)-28.27308, (float)-31.90025 }, 
 new float[] { (float)-19.62229, (float)-24.06179, (float)-26.39476, (float)-27.37066, (float)-28.38618, (float)-30.21026, (float)-36.75971, (float)0 }, 
 new float[] { (float)-17.04894, (float)-21.3542, (float)-22.8806, (float)-23.52033, (float)-23.7384, (float)-25.01727, (float)-28.7377, (float)-34.01962 }, 
 }; 

		private string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
							   "abcdefghijklmnopqrstuvwxyz" +
							   "0123456789-_";

		private char Classify(float[] point)
		{
			int mindist_idx = 0;
			for (int i = 1; i < char_points.Count; i++)
				if (dist(point, char_points[i]) < dist(point, char_points[mindist_idx]))
					mindist_idx = i;

			return chars[mindist_idx];
		}

		private string Classify(Spectrum spec)
		{
			var s = new StringBuilder();
			for (int i = 0; i < spec.SpectrumData.Count; i++)
				s.Append(Classify(spec.SpectrumData[i].Spectrum));

			return s.ToString();
		}

		private float[][] KMeans(float[][] src, int nchars)
		{
			var arity = src[0].Length;
			var cur = new List<float[]>();

			// 1. Fill with random values.
			var used = new HashSet<int>();
			for (int i = 0; i < nchars; i++)
			{
				var idx = random.Next(src.Length);
				while (used.Contains(idx))
					idx = random.Next(src.Length);
				used.Add(idx);
				cur.Add(src[idx]);
			}

			int class_hash = 0, prev_class_hash = -1;
			int iteration = 0;
			while (class_hash != prev_class_hash && iteration < 20)
			{
				iteration++;
				prev_class_hash = class_hash;
				class_hash = 0;

				// 2. Classify all points.
				var classification = new int[src.Length];
				for (int i = 0; i < src.Length; i++)
				{
					var point = src[i];

					int mindist_idx = 0;
					for (int j = 1; j < cur.Count; j++)
						if (dist(point, cur[j]) < dist(point, cur[mindist_idx]))
							mindist_idx = j;

					classification[i] = mindist_idx;
					class_hash = (class_hash * 131313 + mindist_idx) % 1313131313;
				}

				// 3. Count centroids.
				var centroids = new List<float[]>();
				var count = new int[nchars];
				for (int i = 0; i < nchars; i++)
					centroids.Add(new float[arity]);

				for (int i = 0; i < src.Length; i++)
				{
					var c = classification[i];
					for (int j = 0; j < arity; j++)
						centroids[c][j] += src[i][j];
					count[c]++;
				}

				// 4. Write them back.
				for (int i = 0; i < nchars; i++)
					for (int j = 0; j < arity; j++)
						cur[i][j] = centroids[i][j] / Math.Max(count[i], 1);
			}

			return cur.ToArray();
		}

		private void MakeKMeans()
		{
			var spectrums = new List<Tuple<string, Spectrum[]>>();
			foreach (var file in files)
				spectrums.Add(Tuple.Create(file.TagLibFile.Name, file.Spectrums));

			var nspectrums = spectrums[0].Item2.Length;
			int npoints = spectrums.Sum((t) => t.Item2[0].SpectrumData.Count);

			for (int i = 0; i < nspectrums; i++)
			{
				Trace.WriteLine(String.Format("Spectrum {0}: ", i));

				var point_list = new List<float[]>();
				for (int j = 0; j < spectrums.Count; j++)
					for (int k = 0; k < spectrums[j].Item2[i].SpectrumData.Count; k++)
						point_list.Add(spectrums[j].Item2[i].SpectrumData[k].Spectrum);

				var res = KMeans(point_list.ToArray(), 64);

				char_points = new List<float[]>(res);

				for (int j = 0; j < spectrums.Count; j++)
				{
					var filename = spectrums[j].Item1;
					filename = filename.Substring(filename.LastIndexOf('\\')+1);
					while (filename.Length < 20)
						filename = filename + " ";
					var s = Classify(spectrums[j].Item2[i]);
					Trace.WriteLine(String.Format("{0}: {1}", filename, s));
				}
			}
		}

		private int record_stream, enc_stream;
		private RECORDPROC rp;

		private void button1_Click(object sender, RoutedEventArgs e)
		{
			if (!Bass.BASS_RecordInit(-1))
				throw new NotSupportedException();

			rp = new RECORDPROC(RecordProc);
			record_stream = Bass.BASS_RecordStart(8000, 1, BASSFlag.BASS_DEFAULT | BASSFlag.BASS_RECORD_PAUSE, rp, IntPtr.Zero);
			enc_stream = BassEnc.BASS_Encode_Start(record_stream, "out.wav", BASSEncode.BASS_ENCODE_PCM | BASSEncode.BASS_ENCODE_AUTOFREE, null, IntPtr.Zero);
			Bass.BASS_ChannelPlay(record_stream, false);
		}
		
		bool RecordProc(int recordHandle, IntPtr bufferPtr, int length, IntPtr userData)
		{
			short[] buf = new short[length / 2];
			Marshal.Copy(bufferPtr, buf, 0, buf.Length);

			double sum = 0;
			for (int i = 0; i < length / 2; ++i)
				sum += buf[i] * buf[i];

			double pwr = 10 * Math.Log10(sum);
			Trace.WriteLine("pwr : " + pwr.ToString());
			return true;
		}
		
		private string baseurl = "http://192.168.0.130:8000";

		private void button2_Click(object sender, RoutedEventArgs e)
		{
			var res1 = Bass.BASS_ChannelStop(record_stream);
			Bass.BASS_RecordFree();

			var file = reader.ReadFile("out.wav");
			var s = Classify(file.Spectrums[0]);

			Process.Start(baseurl+"/api/search?song="+s);
		}

		private void button3_Click(object sender, RoutedEventArgs e)
		{
			foreach (var file in listBoxResults.SelectedItems.OfType<AudioFile>())
			{
				var client = new WebClient();

				var title = Uri.EscapeUriString(file.TagLibFile.Tag.Title);
				var author = Uri.EscapeUriString(file.TagLibFile.Tag.JoinedPerformers);
				var song = Classify(file.Spectrums[0]);			

				Trace.WriteLine(client.DownloadString(baseurl+"/api/add?author="+author+"&title="+title+"&song="+song));
			}
		}

		private void button4_Click(object sender, RoutedEventArgs e)
		{
			var file = listBoxResults.SelectedItem as AudioFile;

			var s = Classify(file.Spectrums[0]);
			Process.Start(baseurl + "/api/search?song=" + s);
		}

		private void button5_Click(object sender, RoutedEventArgs e)
		{
			Trace.WriteLine("private List<float[]> char_points = new List<float[]> { ");

			for (int i = 0; i < char_points.Count; i++)
			{
				var str = " new float[] { (float)" + String.Join("? (float)", char_points[i]) + " }? ";
				str = str.Replace(",", ".").Replace("?", ",");
				Trace.WriteLine(str);
			}

			Trace.WriteLine(" }; ");
		}

		private void button6_Click(object sender, RoutedEventArgs e)
		{
			Task.Factory.StartNew(() =>
			{
				CountAllStats();
				MakeKMeans();
			});
		}

	}
}
